package com.stark.commons.spring.core.aspect;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;

import com.stark.commons.spring.core.annotation.Log;
import com.stark.commons.spring.core.annotation.Log.Stage;
import com.stark.commons.spring.core.support.aop.MethodExpressionEvaluator;
import com.stark.commons.spring.core.support.log.LogService;

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 日志切面。
 * <p>作用于所有 {@link com.stark.commons.spring.core.annotation.Log @Log} 注解的方法，调用 {@link com.stark.commons.spring.core.support.log.LogService} 接口实现的 log 方法。
 * @author Ben
 * @since 1.0.0
 * @version 1.0.0
 */
@Aspect
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
public class LogAspect {
	
	private LogService logService;
	
	@Around("@annotation(com.stark.commons.spring.core.annotation.Log)")
	public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
		Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
		Log log = method.getAnnotation(Log.class);
		
		if (Stage.BEFORE.equals(log.stage())) {
			_log(joinPoint);
		}
		
		Object result = joinPoint.proceed();
		
		if (Stage.AFTER.equals(log.stage())) {
			_log(joinPoint);
		}
		
		return result;
	}
	
	private void _log(ProceedingJoinPoint joinPoint) {
		String target = "";
		Integer type = -1;
		String businessKey = "";
		String message = "";
		try {
			Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
			Log _log = method.getAnnotation(Log.class);
	        MethodExpressionEvaluator evaluator = new MethodExpressionEvaluator(joinPoint);
	        target = evaluator.getTargetClass().getName() + "#" + evaluator.getTargetMethod().getName();
	        type = _log.type();
	        businessKey = String.valueOf(evaluator.getValue(_log.businessKey()));
	        message = String.valueOf(evaluator.getValue(_log.message()));
	        
			logService.log(evaluator.getTargetClass().getName(), evaluator.getTargetMethod().getName(),
					type, businessKey, message);
		} catch (Exception e) {
			log.error("保存系统日志失败: target={},type={},businessKey={},message={}",
					target, type, businessKey, message, e);
		}
	}
	
}
